package cate.game.role.res.formations;

import cate.common.table.d.GDFormations;
import cate.common.table.d.GDFunc;
import cate.common.table.res.formations.row.FormationsBaseRow;
import cate.common.table.res.formations.row.FormationsLevelUpRow;
import cate.common.util.GameResult;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import com.fasterxml.jackson.annotation.JsonIgnore;
import cp.solution.util.str.Str;
import cate.game.attr.FightAttr;
import cate.game.res.CostSelect;
import cate.game.role.FuncOpenChecker;
import cate.game.role.Role;
import cate.game.role.res.formations.msg.FormationsDataResp;
import cate.game.role.task.TaskGroup;
import easy.java.dev.note.NoteClass;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@NoteClass("阵型")
public class RoleFormations extends FuncOpenChecker {
    @NoteField("等级")
    public int level;
    @NoteField("经验")
    public int exp;

    @NoteField("阵型数据 <阵法ID，阵法数据>")
    public Map<Integer, SingleFormation> formations;

    @Override
    public void initialize(Role role) {
        super.initialize(role);
        if (formations == null) {
            formations = new HashMap<>();
        }
        formations.values().forEach(e -> e.initialize(role));
        if (isOpen() && level == 0) {
            level = 1;
        }
    }

    @Override
    public void onEnter() {
        initFormations();
    }

    private void initFormations() {
        if (isOpen()) {
            TaskGroup taskGroup = role.getTask().getGroup(getFuncId());
            List<FormationsBaseRow> rows = role.getGame().table.formations.base.getList();
            for (FormationsBaseRow row : rows) {
                List<Integer> taskIds = Str.str2IntList(row.taskIdStr,"#");
                if (!formations.containsKey(row.id)) {
                    SingleFormation singleFormation = new SingleFormation(row.id);
                    singleFormation.initialize(role);
                    formations.put(row.id, singleFormation);
                }
                taskGroup.addItemListNoRepeat(taskIds);
            }
        }
    }

    @Override
    public int getFuncId() {
        return GDFunc.FORMATION;
    }

    @Override
    public void onAfterOpen() {
        level = 1;
        initFormations();
        role.getHistory().action.formationsLevel(level);
        noticeUpdate();
    }

    public GameResult<Void> activeFormation(int tid, Map<Integer, CostSelect> csMap) {
        GameResult<Void> r = new GameResult<>();
        if (!formations.containsKey(tid)) {
            return r.fail("不存在该阵型");
        }
        TaskGroup taskGroup = role.getTask().getGroup(getFuncId());
        if (taskGroup == null) {
            return r.fail("无法激活该阵型");
        }
        return formations.get(tid).active(csMap, taskGroup.doneList);
    }

    private boolean anyActive() {
        return formations.values().stream().anyMatch(SingleFormation::isActive);
    }

    public GameResult<Void> levelUp(boolean useItem) {
        GameResult<Void> r = new GameResult<>();
        if (!anyActive()) {
            return r.fail("请先激活一个阵型");
        }
        FormationsLevelUpRow levelRow = getLevelRow();
        if (levelRow == null) {
            return r.fail("无法升级阵型");
        }
        if (StringUtils.isBlank(levelRow.costItemStr) && StringUtils.isBlank(levelRow.costResStr)) {
            return r.fail("阵型已满级");
        }
        MixRes consume = new MixRes();
        if (useItem) {
            consume.addList(new MixRes(GDFormations.COST_ITEM_STR));
        } else {
            if (StringUtils.isNotBlank(levelRow.costItemStr)) {
                consume.addList(new MixRes(levelRow.costItemStr));
            }
            if (StringUtils.isNotBlank(levelRow.costResStr)) {
                consume.addList(new MixRes(levelRow.costResStr));
            }
        }
        GameResult<MixResItem> consumeRes = consume.consume(role);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return r.fail(consumeRes);
        }
        boolean levelUp = levelUp(useItem ? GDFormations.ITEM_ADD_EXP : levelRow.addExp);
        noticeUpdate();
        if (levelUp) {
            role.getHistory().action.formationsLevel(level);
        }
        role.getHistory().action.formationsTimes();
        return r;
    }

    @JsonIgnore
    private FormationsLevelUpRow getLevelRow() {
        return role.getGame().table.formations.levelUp.get(level);
    }

    private boolean levelUp(int addExp) {
        boolean levelUp = false;
        this.exp += addExp;
        FormationsLevelUpRow row = getLevelRow();
        while (row != null && row.exp > 0 && this.exp >= row.exp) {
            this.exp -= row.exp;
            this.level += 1;
            row = getLevelRow();
            levelUp = true;
        }
        return levelUp;
    }

    public Map<Byte, FightAttr> getPosAttrs(int tid) {
        if (!formations.containsKey(tid)) {
            return new HashMap<>();
        }
        return formations.get(tid).getPosAttrs(level);
    }

    public boolean isActive(int tid) {
        return formations.containsKey(tid) && formations.get(tid).active;
    }

    public void noticeUpdate() {
        role.sendNow(new FormationsDataResp(this));
    }
}
